﻿#region Copyright

// /*
// SilverlightInEnterprise
// SilverlightInEnterprise.UnitTesting.Utility
// ViewModelHelper.cs
// 
// Author: Matt Van Horn
// Created 11/16/2011 1:56 PM
// Copyright: Silverlight in the Enterprise www.slinenterprise.com
// 
// Licensed under MS-PL http://www.opensource.org/licenses/MS-PL and while you 
// may use this in anyway you see fit and owe us nothing to do so, we wouldn't mind knowing that you got value out of the work we did (so we will do more) so 
// we ask that you leave a comment on www.slinenterprise.com or on the codeplex site slinenterprise.codeplex.com
// 
// */

#endregion

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

namespace SilverlightInEnterprise.UnitTesting.Utility.PropertyChangeNotification
{
    public class ViewModelHelper
    {
        private INotifyPropertyChanged viewModel;
        private PropertyInfo[] Properties;
        private string expectedPropertyName;
        private string[] errorMessages;
        private int propertiesWithoutNotifications;
        private int propertiesThatFireWrongNotification;
        private List<string> changesSent = new List<string>();
        private List<PropertyChangedEvent> _changeEvents = new List<PropertyChangedEvent>();
        private Action<string, PropertyChangedEvent> OnPropertyChangedCallback;

        public ViewModelHelper(INotifyPropertyChanged viewModel)
        {
            this.viewModel = viewModel;
        }

        public void ProcessProperties(Action<string, PropertyChangedEvent> OnPropertyChangedCallback)
        {
            this.OnPropertyChangedCallback = OnPropertyChangedCallback;
            this.Properties = this.viewModel.GetType().GetProperties(BindingFlags.Public);
            this.viewModel.PropertyChanged += OnPropertyChanged;
            object newValue = null;
            foreach (var property in Properties)
            {
                if (property.PropertyType == typeof (string))
                {
                    newValue = " this is a test of setting a string ";
                }
                else if (property.PropertyType == typeof (int))
                {
                    newValue = int.MaxValue/2;
                }
                else if (property.PropertyType == typeof (decimal))
                {
                    newValue = decimal.MaxValue/2;
                }
                else if (property.PropertyType == typeof (double))
                {
                    newValue = double.MaxValue/2;
                }
                else if (property.PropertyType == typeof (long))
                {
                    newValue = long.MaxValue/2;
                }
                else if (property.PropertyType == typeof (short))
                {
                    newValue = short.MaxValue/2;
                }
                else if (property.PropertyType == typeof (byte))
                {
                    newValue = 153;
                }
                else if (property.PropertyType == typeof (object))
                {
                    newValue = new object();
                }
                else if (property.PropertyType.IsClass)
                {
                    newValue = null;
                }
                this.ChangeValue(property, newValue);
            }
        }

        public List<PropertyChangedEvent> ChangeEvents
        {
            get { return _changeEvents; }
        }

        private void ChangeValue(PropertyInfo property, object value)
        {
            this.changesSent.Clear();
            object orignal = property.GetValue(this.viewModel, new object[0]);
            Exception ex = null;
            try
            {
                property.SetValue(this.viewModel, value, new object[0]);
            }
            catch (Exception e)
            {
                ex = e;
            }
            object actual = property.GetValue(this.viewModel, new object[0]);
            PropertyChangedEvent evt = new PropertyChangedEvent(property.Name, changesSent.ToArray(),
                                                                changesSent.Count > 0, ex, orignal, value, actual);
            if (this.OnPropertyChangedCallback != null)
                this.OnPropertyChangedCallback(property.Name, evt);
            this.ChangeEvents.Add(evt);
        }

        private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.changesSent.Add(e.PropertyName);
        }
    }
}